package CheckersApplet;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Panel;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.imageio.ImageIO;

public class CheckersPanel extends Panel {
	/*
	 * layout of checker board in a 36 piece array 0 1 2 3 4 5 6 7 8X 9 10 11 12
	 * 13 14 15 16 17X 18 19 20 21 22 23 24 25 26X 27 28 29 30 31 32 33 34 35X
	 * 
	 * places labeled X are null places
	 * 
	 * all single moves are done in increments of +/-4 and +/-5 jumps are done
	 * in increments of +/-8 +/-10
	 * 
	 * if any move would land in a null place, then it can't be done
	 */

	// Checkers myAppl;

	protected BoardGrid mainGrid[] = new BoardGrid[36];
	protected static int redType = 0;
	protected static int blackType = 1;
	protected static int redKingType = 2;
	protected static int blackKingType = 3;
	protected static int emptyType = -1;
	protected static int nullType = -2;

	protected static int oppositeType(int type) {
		return (int) ((type >= 0) ? ((type + 1) % 2) : type);
	}

	protected static int kingType(int type) {
		return (int) ((type == 0 || type == 1) ? (type + 2) : type);
	}

	protected static int plainType(int type) {
		return (int) ((type >= 0) ? (type % 2) : type);
	}

	protected int mainBoard[] = new int[36];
	protected int preBoard[] = new int[36];

	protected void undo() {
		System.arraycopy(preBoard, 0, mainBoard, 0, 36);
		repaint();
		// myAppl.play(myAppl.getCodeBase(), "audio/ding.au");
	}

	protected int carryPiece;
	protected int userColor;

	protected boolean movingPiece = false;
	protected boolean didjump = false;
	protected int carryPlace;
	protected int carryXpos, carryYpos;
	protected int tough = 0;
	protected int defTough = 2;
	protected boolean waiting = false;

	public void setToughness(int toTough) {
		tough = toTough;
	}
	
	private GameState gameState = GameState.NOTSTARTED; 
	
	public GameState getGameState(){
		updateGameState();
		return gameState;
	};

	String color;
	String defColor = "black";

	protected void setColor(String toColor) {
		color = toColor;
		if (toColor.equals("red"))
			userColor = 0;
		else if (toColor.equals("black"))
			userColor = 1;
	}

	// protected Panel controlPanel;

	public double score() {
		return score(userColor);
	}

	public double score(int type) {
		// myErr("score: "+type);
		double t = score(type, mainBoard);
		// myErr("score: return "+t);
		if (t < 0 || t > 24)
			myErr("score(i)");
		return t;
	}

	public double score(int type, int aBoard[]) {
		double reds, blacks, ret = 0.0;
		int loop;

		for (reds = blacks = loop = 0; loop < 36; loop++) {
			switch (aBoard[loop]) {
			case 2: // redKingType:
				reds += 1;
			case 0:// redType:
				reds += 1;
				break;
			case 3:// blackKingType:
				blacks += 1;
			case 1:// blackType:
				blacks += 1;
				break;
			default:
				break;
			}
		}
		switch (type) {
		case 0:// redType:
			if (reds == 0) {
				return 0.0;
			}
			if (blacks == 0) {
				return 24.0;
			}
			ret = reds / blacks;
			if (ret > 24 || ret < 0)
				myErr("score(i,i)");
			return ret;
		case 1:// blackType:
			if (reds == 0) {
				return 24.0;
			}
			if (blacks == 0) {
				return 0.0;
			}
			ret = blacks / reds;
			if (ret > 24 || ret < 0)
				myErr("score(i,i)");
			return ret;
		default:
			break;
		}
		return ret;
	}

	// #returns < zero if the piece could not jump
	// #or returns the place to jump to
	// #
	// #int piece_could_jump(int piece, color, board)
	protected int piece_could_jump(int piececount, int piececolor, int tBoard[]) {
		int j[] = new int[4];
		int ret = -1;
		int loop;

		if (plainType(piececolor) != redType
				&& plainType(piececolor) != blackType)
			return -1;
		// myErr("piece_could_jump: "+piececount+", "+piececolor+", "+tBoard+", "+fromPiece);

		j[0] = piececount - 8;
		j[1] = piececount - 10;
		j[2] = piececount + 8;
		j[3] = piececount + 10;

		for (loop = 0; loop < 4; loop++) {
			// TODO: 31, 34?
			if (j[loop] >= 0 && j[loop] <= 34) {
				if (valid_move(piececount, j[loop], tBoard, piececolor)) {
					// myErr( "JA!");
					ret = j[loop];
				}
			}
		}

		// myErr("piece_could_jump: "+ret);
		// if(ret>0) {
		// while((ret=j[(int)(Math.random()*4.0) - 1])<0);
		// }
		return ret;
	}

	// #returns a -1 if the color could not jump otherwise return the index of
	// #the jumpable piece
	// #int could_jump(char *color, board)
	protected int could_jump(int jumpcol, int tBoard[]) {
		int ret = -1;
		int loop;

		// myErr("could_jump: "+jumpcol+", "+tBoard);

		for (loop = 0; ret < 0 && loop < 36; loop++) {
			if (plainType(tBoard[loop]) == jumpcol) {
				if (piece_could_jump(loop, jumpcol, tBoard) >= 0) {
					ret = loop;
				}
			}
		}
		// myErr("could_jump: "+ret);
		return ret;
	}

	protected boolean valid_move(int from, int to, int aBoard[], int colorfor) {
		if (plainType(colorfor) == userColor) {
			return (to >= 0 && to <= 35 && from >= 0 && from <= 35
					&& plainType(aBoard[from]) == colorfor
					&& aBoard[to] == emptyType && ((from - to == 4 || from - to == 5)
					|| ((from - to == 10 && plainType(aBoard[from - 5]) == oppositeType(colorfor)) || (from
							- to == 8 && plainType(aBoard[from - 4]) == oppositeType(colorfor))) || (aBoard[from] == kingType(colorfor) && ((to
					- from == 4 || to - from == 5) || ((to - from == 10 && plainType(aBoard[from + 5]) == oppositeType(colorfor)) || (to
					- from == 8 && plainType(aBoard[from + 4]) == oppositeType(colorfor)))))));
		} else {
			return (to >= 0 && to <= 35 && from >= 0 && from <= 35
					&& plainType(aBoard[from]) == colorfor
					&& aBoard[to] == emptyType && ((to - from == 4 || to - from == 5)
					|| ((to - from == 10 && plainType(aBoard[from + 5]) == oppositeType(colorfor)) || (to
							- from == 8 && plainType(aBoard[from + 4]) == oppositeType(colorfor))) || (aBoard[from] == kingType(colorfor) && ((from
					- to == 4 || from - to == 5) || ((from - to == 10 && plainType(aBoard[from - 5]) == oppositeType(colorfor)) || (from
					- to == 8 && plainType(aBoard[from - 4]) == oppositeType(colorfor)))))));
		}
	}

	// int retperf[] = new int[36];
	protected int[] perform_move(int from, int to, int zBoard[]) {
		// System.arraycopy(zBoard,0,retperf,0,36);
		zBoard[to] = zBoard[from];
		zBoard[from] = emptyType;
		didjump = false;
		if ((to >= 0 && to <= 3) || (to >= 31 && to <= 35))
			zBoard[to] = kingType(zBoard[to]);
		if (to > from) {
			// if(to-from<=5) return zBoard;
			if (to - from == 8) {
				didjump = true;
				zBoard[from + 4] = emptyType;
			} else if (to - from == 10) {
				didjump = true;
				zBoard[from + 5] = emptyType;
			}
		} else if (to < from) {
			// if(from-to<=5) return zBoard;
			if (from - to == 8) {
				didjump = true;
				zBoard[from - 4] = emptyType;
			} else if (from - to == 10) {
				didjump = true;
				zBoard[from - 5] = emptyType;
			}
		}
		return zBoard;
	}

	protected void myErr(String message) {
		System.out.println(message);
	}

	// #recursively finds the score for the tree rooted at this
	// #board if the next move is made by the color
	// #
	// #float scores_for_moves(colorfor, colormove, board, depth)
	protected double scores_for_moves(int colorfor, int colormove,
			int aBoard[], int depth) {
		// Board aBoard=tBoard;
		int piececount = 0;
		int piece = 0;
		int oddrow = 0;
		int moves[] = new int[8];
		int loop = 0;
		int newboard[] = new int[36];
		int t = 0;
		double temp = 0.0;
		double ret = 0.0, lowest = 25.0, highest = -1.0;
		int a = 0;
		boolean valid = false, wasValid = false, anyValid = false;

		ret = score(colormove, aBoard);
		if (ret < 0 || ret > 24)
			myErr("ret out of bounds: " + ret + " :scores_for_moves:[no depth]");
		if (depth == 0 || ret == 0 || ret == 24) {
			return ret;
		}

		if ((could_jump(colormove, aBoard)) >= 0) {
			for (piececount = 0; piececount < 36; piececount++) {

				piece = aBoard[piececount];

				t = piece_could_jump(piececount, colormove, aBoard);
				if (t >= 0) {
					valid = valid_move(piececount, t, aBoard, colormove);
					System.arraycopy(aBoard, 0, newboard, 0, 36);
					if (valid)
						perform_move(piececount, t, newboard);
					wasValid = valid;
					while (wasValid
							&& didjump
							&& (a = piece_could_jump(t, colormove, newboard)) >= 0) {
						wasValid = valid_move(t, a, newboard, colormove);
						if (wasValid)
							perform_move(t, a, newboard);
						t = a;
					}

					if (valid) {
						anyValid = true;
						temp = scores_for_moves(colorfor,
								oppositeType(colormove), newboard, depth - 1);
						if (temp < 0 || temp > 24)
							myErr("temp out of bounds: " + temp
									+ " :scores_for_moves[must jump]");
						// myErr("temp: "+temp+" highest: "+highest+" lowest: "+lowest);
						if (temp > highest) {
							highest = temp;
						}
						if (temp < lowest) {
							lowest = temp;
						}
					}
				}
			}
		} else {
			for (piececount = 0; piececount < 36; piececount++) {
				piece = aBoard[piececount];
				if (plainType(piece) == colormove) {

					moves[0] = piececount + 5;
					moves[1] = piececount - 5;
					moves[2] = piececount + 4;
					moves[3] = piececount - 4;
					moves[4] = piececount + 8;
					moves[5] = piececount - 8;
					moves[6] = piececount + 10;
					moves[7] = piececount - 10;

					for (loop = 0; loop < 8; loop++) {
						a = moves[loop];
						if ((a >= 0) && (a <= 35)) {

							valid = valid_move(piececount, a, aBoard, colormove);
							System.arraycopy(aBoard, 0, newboard, 0, 36);
							if (valid)
								perform_move(piececount, a, newboard);

							wasValid = valid;
							while (wasValid
									&& didjump
									&& (t = piece_could_jump(a, colormove,
											newboard)) >= 0) {
								wasValid = valid_move(a, t, newboard, colormove);
								if (wasValid)
									perform_move(a, t, newboard);
								a = t;
							}
							if (valid) {
								anyValid = true;
								temp = scores_for_moves(colorfor,
										oppositeType(colormove), newboard,
										depth - 1);
								if (temp < 0 || temp > 24)
									myErr("temp out of bounds: " + temp
											+ " :scores_for_moves");
								// myErr("temp: "+temp+" highest: "+highest+" lowest: "+lowest);
								if (temp > highest)
									highest = temp;
								if (temp < lowest)
									lowest = temp;
							}
						}
					}

				}

			}
		}

		if (lowest < 0 || lowest > 24) {
			// myErr("lowest out of bounds: "+lowest+"scores_for_moves");
			lowest = score(colormove, aBoard);
		}

		ret = 24.0 - lowest;

		return ret;
	}

	private int revertMove(int pos) {
		return 34 - pos;
	}

	public ArrayList<Move> makeMove(ArrayList<Move> movesList) {
		ArrayList<Move> moves = null;
		if (movesList == null || movesList.isEmpty())
			System.out.println("Error! Empty move message received!!!!");
		for (Move move : movesList)
			moves = makeMove(move.from, move.to);
		return moves;
	}

	// #returns a new board for a color's move
	// #
	// #board make_move(color, board)
	protected ArrayList<Move> make_move(int colorfor, int aBoard[]) {
		int colormove = 0;
		int piececount = 0, a = 0;
		int piecet = 0, t = 0;
		int newboard[] = new int[36];
		int piece = 0;
		int oddrow = 0, loop = 0;
		int moves[] = new int[8];
		double ret = 0.0;
		double temp = 0.0;
		double highest = -1.0, lowest = 25.0;
		int highBoard[] = new int[36], lowBoard[] = new int[36];
		boolean valid = false, wasValid = false;
		int from = 0, to = 0;
		// Move newMove;
		// Move bestMove;
		// newMove = new Move(-1, -1);
		// bestMove = new Move(-1, -1);
		ArrayList<Move> tempList = new ArrayList<Move>();
		ArrayList<Move> movesList = new ArrayList<Move>();
		// myErr("make_move: "+colorfor+", "+aBoard);

		colormove = colorfor;

		piececount = 0;

		System.arraycopy(aBoard, 0, lowBoard, 0, 36);
		System.arraycopy(aBoard, 0, highBoard, 0, 36);

		if ((could_jump(colorfor, aBoard)) >= 0) {
			for (piececount = 0; piececount < 36; piececount++) {

				tempList.clear();
				piece = aBoard[piececount];

				t = piece_could_jump(piececount, colorfor, aBoard);
				if (t >= 0) {
					valid = valid_move(piececount, t, aBoard, colorfor);
					System.arraycopy(aBoard, 0, newboard, 0, 36);
					if (valid) {
						// newMove = new Move(piececount, t);
						tempList.add(new Move(piececount, t));
						perform_move(piececount, t, newboard);
					}
					from = piececount;
					to = t;
					wasValid = valid;
					while (wasValid
							&& didjump
							&& (a = piece_could_jump(t, colorfor, newboard)) >= 0) {
						wasValid = valid_move(t, a, newboard, colorfor);
						if (wasValid) {
							// newMove = new Move(t, a);
							tempList.add(new Move(t, a));
							perform_move(t, a, newboard);
						}
						from = t;
						to = a;
						t = a;
					}

					if (valid) {
						temp = scores_for_moves(colorfor,
								oppositeType(colorfor), newboard, tough);
						if (temp < 0 || temp > 24)
							myErr("temp out of bounds: " + temp
									+ " :make_move[must jump]");
						// myErr("temp: "+temp+" highest: "+highest+" lowest: "+lowest);
						if (temp > highest) {
							highest = temp;
							System.arraycopy(newboard, 0, highBoard, 0, 36);
						}
						if (temp < lowest) {
							lowest = temp;
							// bestMove = new Move(newMove.from, newMove.to);
							movesList = (ArrayList<Move>) tempList.clone();
							System.arraycopy(newboard, 0, lowBoard, 0, 36);
						}
					}
				}
			}
		} else {
			for (piececount = 0; piececount < 36; piececount++) {
				piece = aBoard[piececount];

				if (plainType(piece) == colorfor) {
					moves[0] = piececount + 5;
					moves[1] = piececount - 5;
					moves[2] = piececount + 4;
					moves[3] = piececount - 4;
					moves[4] = piececount + 8;
					moves[5] = piececount - 8;
					moves[6] = piececount + 10;
					moves[7] = piececount - 10;

					for (loop = 0; loop < 8; loop++) {
						tempList.clear();
						a = moves[loop];
						if (a >= 0 && a <= 35) {

							valid = valid_move(piececount, a, aBoard, colormove);
							System.arraycopy(aBoard, 0, newboard, 0, 36);
							if (valid) {
								// newMove = new Move(piececount, a);
								tempList.add(new Move(piececount, a));
								perform_move(piececount, a, newboard);
							}
							from = piececount;
							to = a;

							wasValid = valid;
							while (wasValid
									&& didjump
									&& (t = piece_could_jump(a, colormove,
											newboard)) >= 0) {
								wasValid = valid_move(a, t, newboard, colormove);
								// newMove = new Move(a, t);
								tempList.add(new Move(a, t));
								perform_move(a, t, newboard);
								from = a;
								to = t;
								a = t;
							}
							if (valid) {
								temp = scores_for_moves(colorfor,
										oppositeType(colorfor), newboard, tough);
								if (temp < 0 || temp > 24)
									myErr("temp out of bounds: " + temp
											+ " :make_move[must jump]");
								// myErr("temp: "+temp+" highest: "+highest+" lowest: "+lowest);
								if (temp > highest) {
									highest = temp;
									System.arraycopy(newboard, 0, highBoard, 0,
											36);
								}
								if (temp < lowest) {
									lowest = temp;
									movesList = (ArrayList<Move>) tempList.clone();
									System.arraycopy(newboard, 0, lowBoard, 0,
											36);
								}
							}
						}
					}
				}
			}
		}

		if (lowest < 0 || lowest > 24) {
			lowest = score(colormove, aBoard);
			// myErr("lowest out of bounds: "+lowest+"make_move");
		}

		ret = 24.0 - lowest;

		if (ret == 24.0) {
			//System.out.println("I will win within " + tough + " moves.");
		} else if (ret == 0.0) {
			//System.out.println("I will lose within " + tough + " moves.");
		}
		System.arraycopy(lowBoard, 0, aBoard, 0, 36);
		// System.out.println("-------------");
		// System.out.println("From: " + Integer.toString(bestMove.from) +
		// " To: " + Integer.toString(bestMove.to));
		// for (Move move : movesList)
		// System.out.println("From: " + Integer.toString(move.from) + " To: "
		// + Integer.toString(move.to));
		// System.out.println("-------------");
		return movesList;
	}

	protected boolean pieceIsInside(int piece, int x, int y) {
		return (x >= mainGrid[piece].xpos && y >= mainGrid[piece].ypos
				&& x <= (mainGrid[piece].xpos + mainGrid[piece].xwidth) && y <= (mainGrid[piece].ypos + mainGrid[piece].ywidth));
	}

	int couldjump = -1;

	public ArrayList<Move> makeMove(int from, int to) {
		int loop = to;
		couldjump = could_jump(plainType(mainBoard[from]), mainBoard);
		carryPiece = mainBoard[from];
		carryPlace = from;
		carryXpos = mainGrid[from].xpos;
		carryYpos = mainGrid[from].ypos;
		mainBoard[from] = emptyType;
		boolean valid;
		ArrayList<Move> opponentMoves = new ArrayList<Move>();

		mainBoard[carryPlace] = carryPiece;
		System.arraycopy(mainBoard, 0, preBoard, 0, 36);
		valid = valid_move(carryPlace, loop, mainBoard, plainType(carryPiece));
		if (valid) {
			perform_move(carryPlace, loop, mainBoard);
			movingPiece = false;
			repaint();
			if (score() == 0) {
				updateGameState();
				//newGame();// computer won
			} else if (score() == 24) {
				updateGameState();
				//newGame();// user won
			} else { // keep going
				if (couldjump >= 0 && !didjump) {
					mainBoard[(couldjump == carryPlace) ? loop : couldjump] = emptyType;
				}
				if (didjump
						&& piece_could_jump(loop, plainType(mainBoard[loop]),
								mainBoard) >= 0) {
					// user can jump again
				} else { // my move
					waiting = true;
					// myAppl.showStatus("Checkers: making move...");
					repaint();
					opponentMoves = make_move(oppositeType(userColor),
							mainBoard);
					// myAppl.showStatus("");
					waiting = false;
					if (score() == 0) {
						updateGameState();//
						//newGame();
						// computer won
					} else if (score() == 24) {
						updateGameState();
						//newGame();
						// user won
					}
				}
			}
			System.gc();

			repaint();
			return opponentMoves;
		}

		mainBoard[carryPlace] = carryPiece;
		movingPiece = false;
		System.gc();

		repaint();
		return opponentMoves;
	}

	private void updateGameState() {
		double score = score();
		if (score == 24){
			if (color.equals("black"))
				gameState = GameState.BLACKWON;
			else gameState = GameState.REDWON;
		}
		else if (score == 0){
			if (color.equals("red"))
				gameState = GameState.BLACKWON;
			else 
				gameState = GameState.REDWON;
		}
		else 
			gameState = GameState.INPROGRESS;
		
		//System.out.println("GameState updated!");
	}

	public boolean mouseDown(Event evt, int x, int y) {
		int loop;
		Graphics g = getGraphics();

		// myErr("\nmouseDown");

		for (loop = 0; loop < 36; loop++) {
			if (pieceIsInside(loop, x, y)
			// && (mainBoard[loop] != emptyType) ) {
					&& (plainType(mainBoard[loop]) == userColor)) {
				// myErr("mouse is inside piece " + loop);

				couldjump = could_jump(plainType(mainBoard[loop]), mainBoard);
				carryPiece = mainBoard[loop];
				carryPlace = loop;
				carryXpos = mainGrid[loop].xpos;
				carryYpos = mainGrid[loop].ypos;
				mainBoard[loop] = emptyType;

				g.drawImage(pieceImage(mainBoard[loop]), mainGrid[loop].xpos,
						mainGrid[loop].ypos, mainGrid[loop].xwidth,
						mainGrid[loop].ywidth, this);

				movingPiece = true;

				g.drawImage(pieceImage(carryPiece), carryXpos, carryYpos,
						mainGrid[carryPlace].xwidth,
						mainGrid[carryPlace].ywidth, this);

				return true;
			}
		}

		return true;
	}

	public boolean mouseUp(Event evt, int x, int y) {
		int loop;
		Graphics g = getGraphics();
		boolean valid;

		// myErr("\nmouseUp");

		if (!movingPiece) {
			return true;
		}

		for (loop = 0; loop < 36; loop++) {
			if (pieceIsInside(loop, x, y) && (mainBoard[loop] == emptyType)) {
				// myErr("mouse is inside piece " + loop);
				mainBoard[carryPlace] = carryPiece;
				System.arraycopy(mainBoard, 0, preBoard, 0, 36);
				// couldjump=could_jump(carryPiece, mainBoard);
				valid = valid_move(carryPlace, loop, mainBoard,
						plainType(carryPiece));
				if (valid) {
					perform_move(carryPlace, loop, mainBoard);
					// System.arraycopy(retperf,0,mainBoard,0,36);
					// mainBoard[carryPlace]=emptyType;
					// mainBoard[loop]=carryPiece;
					// myErr("Score: " + score());
					movingPiece = false;
					repaint();
					if (score() == 0) {
						// myAppl.play(myAppl.getCodeBase(), "audio/joy.au");
						newGame();
						// computer won
					} else if (score() == 24) {
						// myAppl.play(myAppl.getCodeBase(), "audio/joy.au");
						newGame();
						// user won
					} else { // keep going
								// play(getCodeBase(), "audio/beep.au");
								// myErr("couldjump: " + couldjump +
								// " didjump: " + didjump);
								// could've jumped but didn't
						if (couldjump >= 0 && !didjump) {
							mainBoard[(couldjump == carryPlace) ? loop
									: couldjump] = emptyType;
						}
						if (didjump
								&& piece_could_jump(loop,
										plainType(mainBoard[loop]), mainBoard) >= 0) {
							// user can jump again
						} else { // my move
							waiting = true;
							// myAppl.showStatus("Checkers: making move...");
							repaint();
							make_move(oppositeType(userColor), mainBoard);
							// myAppl.showStatus("");
							waiting = false;
							// myAppl.play(myAppl.getCodeBase(),
							// "audio/ding.au");
							// myErr("score after computer : " + score());
							if (score() == 0) {
								// myAppl.play(myAppl.getCodeBase(),
								// "audio/joy.au");
								newGame();
								// computer won
							} else if (score() == 24) {
								// myAppl.play(myAppl.getCodeBase(),
								// "audio/joy.au");
								newGame();
								// user won
							}
						}
					}
					System.gc();

					repaint();
					return true;
				} else {
					// myErr("Invalid move");
					break;
				}
			}
		}
		mainBoard[carryPlace] = carryPiece;
		movingPiece = false;
		System.gc();

		repaint();
		return true;
	}

	public boolean mouseDrag(Event evt, int x, int y) {

		if (movingPiece) {
			carryXpos = (x - (mainGrid[carryPiece].xwidth / 2));
			carryYpos = (y - (mainGrid[carryPiece].ywidth / 2));
			repaint();
		}

		return true;
	}

	protected ArrayList<Move> newGame() {
		gameState = GameState.INPROGRESS;
		int loop;
		Dimension d = size();
		int xoff = d.width / 8;
		int yoff = d.height / 8;
		ArrayList<Move> moves = null;

		// myAppl.play(myAppl.getCodeBase(), "audio/return.au");
		if (color.equals("red")) {
			userColor = redType;
			for (loop = 0; loop < 13; loop++) {
				mainBoard[loop] = blackType;
			}
			for (loop = 13; loop < 22; loop++) {
				mainBoard[loop] = emptyType;
			}
			for (loop = 22; loop < 35; loop++) {
				mainBoard[loop] = redType;
			}
		} else {
			userColor = blackType;
			for (loop = 0; loop < 13; loop++) {
				mainBoard[loop] = redType;
			}
			for (loop = 13; loop < 22; loop++) {
				mainBoard[loop] = emptyType;
			}
			for (loop = 22; loop < 35; loop++) {
				mainBoard[loop] = blackType;
			}
		}

		mainBoard[8] = nullType;
		mainBoard[17] = nullType;
		mainBoard[26] = nullType;
		mainBoard[35] = nullType;
		System.arraycopy(mainBoard, 0, preBoard, 0, 36);

		repaint();
		
		if (userColor == redType) {
			waiting = true;
			repaint();
			moves = make_move(oppositeType(userColor), mainBoard);
			waiting = false;
			// myAppl.play(myAppl.getCodeBase(), "audio/ding.au");
			if (score() == 0) {
				// myAppl.play(myAppl.getCodeBase(), "audio/joy.au");
				newGame();
				// computer won
			} else if (score() == 24) {
				// myAppl.play(myAppl.getCodeBase(), "audio/joy.au");
				newGame();
				// user won
			}
		}

		return moves;
	}

	public CheckersPanel() {
		int loop;
		String param;

		// myErr("init begin");

		for (loop = 0; loop < 36; loop++) {
			mainGrid[loop] = new BoardGrid();
		}
		try {
			// System.out.println(System.)
			black_black = ImageIO.read(new File("images/black_black.gif"));
			black_black_king = ImageIO.read(new File(
					"images/black_black_king.gif"));
			black_empty = ImageIO.read(new File("images/black_empty.gif"));
			black_red = ImageIO.read(new File("images/black_red.gif"));
			black_red_king = ImageIO
					.read(new File("images/black_red_king.gif"));
			red_empty = ImageIO.read(new File("images/red_empty.gif"));

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		param = null;
		// param = myAppl.getParameter("COLOR");
		color = (param != null) ? param : defColor;
		// param = myAppl.getParameter("TOUGH");

		tough = (param != null) ? Integer.parseInt(param) : defTough;

		newGame();
		// myErr("toughness: "+tough+"\ninit end");
	}

	public void update(Graphics g) {
		paint(g);
	}

	// class CheckersCanvas extends Canvas {

	protected Image black_black, black_black_king, black_empty, black_red,
			black_red_king, red_empty;

	Image offscreen = null;
	Dimension offscreensize = null;
	Graphics offgraphics = null;

	Color red = new Color((float) 1.0, (float) 0.0, (float) 0.0);
	Color black = Color.black;
	Color darkgray = Color.darkGray;
	Color darkred = new Color((float) 0.7, (float) 0.0, (float) 0.0);
	Color white = Color.white;
	Color gray = Color.gray;
	Color yellow = Color.yellow;

	// public CheckersCanvas(

	public Image pieceImage(int colorfor) {
		switch (colorfor) {
		case 0: /* redType: */
			return black_red;
		case 1: /* blackType: */
			return black_black;
		case 3:/* blackKingType: */
			return black_black_king;
		case 2:/* redKingType: */
			return black_red_king;
		default:
			return black_empty;
		}
		// return null;
	}

	public void paint(Graphics g) {
		Dimension d = size();
		int x, y, loop, lx, ly;
		int xoff = d.width / 8;
		int yoff = d.height / 8;

		// myErr("update begin");

		if ((offscreen == null) || (d.width != offscreensize.width)
				|| (d.height != offscreensize.height)) {
			offscreen = createImage(d.width, d.height);
			offscreensize = d;
			offgraphics = offscreen.getGraphics();
			offgraphics.setFont(getFont());
		}

		offgraphics.setColor(getBackground());
		offgraphics.fillRect(0, 0, d.width, d.height);

		// myErr("offgraphics done");

		// if(mainGrid==null) myErr("Insanity!");

		loop = 0;
		for (ly = 0, y = 1; ly < 8; ly++, y += yoff) {
			for (lx = 0, x = 1; lx < 8; lx++, x += xoff) {
				if ((lx % 2) != (ly % 2) && loop < 35) {
					if (loop == 8 || loop == 17 || loop == 26) {
						loop++;
					}
					mainGrid[loop].xpos = x;
					mainGrid[loop].ypos = y;
					mainGrid[loop].xwidth = xoff - 2;
					mainGrid[loop].ywidth = yoff - 2;
					offgraphics.drawImage(pieceImage(mainBoard[loop++]), x, y,
							xoff - 2, yoff - 2, this);
				} else {
					// myErr("blank image");
					offgraphics.drawImage(red_empty, x, y, xoff - 2, yoff - 2,
							this);
				}
			}
		}

		if (movingPiece) {
			offgraphics.drawImage(pieceImage(carryPiece), carryXpos, carryYpos,
					mainGrid[carryPlace].xwidth, mainGrid[carryPlace].ywidth,
					this);
		}

		// if(waiting) {
		// offgraphics.setColor(Color.white);
		// offgraphics.fillRect(d.width/3, d.height/3, 2*d.width/3,
		// 2*d.height/3);
		// }

		g.drawImage(offscreen, 0, 0, null);
		// myErr("g.drawImage done");
		// myErr("update end");
	}
}
